package vista.ventanas;

import javax.swing.JFrame;
import javax.swing.JRadioButton;

import logica.Entidad;
import logica.Jerarquia;
import logica.JerarquiaException;
import logica.SinNombreException;
import vista.paneles.ElementoNoExistenteException;
import vista.paneles.NingunElementoSeleccionadoException;
import vista.paneles.PanelBotonDeOpciones;
import vista.paneles.PanelParLabelCombo;
import vista.paneles.PanelParLabelText;
import vista.paneles.PanelReferenciaEntidades;

import java.util.List;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.MouseListener;

@SuppressWarnings("serial")
public class VentanaJerarquia extends SubVentana implements IVentanaConReferenciaAEntidades{

	private final static int PANEL_INFORMACION_ALTO = 23 * ConstantesVista.RENGLON;
	
	private PanelParLabelText panelNombre;
	private PanelParLabelCombo panelPadre;
	private PanelBotonDeOpciones panelParticion;
	private PanelBotonDeOpciones panelSolapamiento;
	private PanelReferenciaEntidades panelEntidadesEspecializadas;
	
	private Jerarquia jerarquia;

	public VentanaJerarquia(JFrame frame, List<Entidad> entidadesExistentes) 
	{
		super(frame, "Crear Jerarquia", PANEL_INFORMACION_ALTO);
		
		this.setEntidadesExistentes(entidadesExistentes);
		
		this.jerarquia = null;
	}
	
	public VentanaJerarquia(JFrame frame, List<Entidad> entidadesExistentes, Jerarquia jerarquiaAEditar) throws ElementoNoExistenteException 
	{
		super(frame, "Editar Jerarquia", PANEL_INFORMACION_ALTO);
		
		this.setEntidadesExistentes(entidadesExistentes);
		
		this.jerarquia = jerarquiaAEditar;
		this.setInformacionJerarquiaEditada();
	}

	private void setInformacionJerarquiaEditada() throws ElementoNoExistenteException
	{
		this.panelNombre.setInformacion(jerarquia.getNombre());
		this.panelPadre.seleccionarDato(jerarquia.getEntidadPadre());
		this.panelPadre.setEnabled(false);
		
		this.panelEntidadesEspecializadas.agregarEntidadesExternas(jerarquia.getEntidadesEspecializadas());
		
		if (jerarquia.esParticionCompleta())
			this.panelParticion.seleccionar(ConstantesVista.PARTICION_COMPLETA);
		else
			this.panelParticion.seleccionar(ConstantesVista.PARTICION_PARCIAL);
		
		if (jerarquia.haySolapamiento())
			this.panelSolapamiento.seleccionar("Si");
		else
			this.panelSolapamiento.seleccionar("No");
	}
	
	public Jerarquia getJerarquia() throws JerarquiaException, SinNombreException, NingunElementoSeleccionadoException
	{
		String nombre = this.panelNombre.getInformacion(); 
		if (nombre.isEmpty())
			nombre = " ";
		
		if (jerarquia == null)
			return new Jerarquia(nombre, this.getEntidadPadre(), this.getEntidadesEspecializadas(),
				this.getParticionCompleta(), this.getSolapamiento());
		
		this.jerarquia.setNombre(nombre);
		this.jerarquia.setEsParticionCompleta(this.getParticionCompleta());
		this.jerarquia.setHaySolapamiento(this.getSolapamiento());
		this.jerarquia.setEntidadEspecilizada(this.getEntidadesEspecializadas());
		
		return this.jerarquia;
	}
	
	public boolean getParticionCompleta()
	{
		return (this.panelParticion.getOpcionElegida().getText().compareToIgnoreCase(ConstantesVista.PARTICION_COMPLETA) == 0);
	}
	
	public boolean getSolapamiento()
	{
		return (this.panelSolapamiento.getOpcionElegida().getText().compareToIgnoreCase(("Si"))) == 0;
	}
	
	public Entidad getEntidadPadre() throws NingunElementoSeleccionadoException
	{
		try
		{
			return (Entidad)this.panelPadre.getDatoSeleccionado();
		}
		catch(NingunElementoSeleccionadoException nada)
		{
			throw new NingunElementoSeleccionadoException("No se ha seleccionado ninguna Entidad Padre");
		}

	}
	
	public List<Entidad> getEntidadesEspecializadas()
	{
		return this.panelEntidadesEspecializadas.getReferenciaEntidades();

	}
	
	private void setEntidadesExistentes(List<Entidad> entidades)
	{
		this.panelPadre.setDatosCombo(entidades);		
	}

	
	/* para los eventos */
	@Override
	public void escucharEventoAgregarEntidad(MouseListener controlador)
	{
		this.panelEntidadesEspecializadas.escucharEventoAgregar(controlador);
	}
	
	@Override
	public void escucharEventoQuitarEntidad(MouseListener controlador)
	{
		this.panelEntidadesEspecializadas.escucharEventoQuitar(controlador);
	}
	
	@Override
	public void agregarEntidadExterna(Entidad entidadEspecializada)
	{
		this.panelEntidadesEspecializadas.agregarEntidadExterna(entidadEspecializada);
	}
	
	@Override
	public void quitarEntidadExterna()
	{
		this.panelEntidadesEspecializadas.quitarEntidadExterna();
	}
	
	/* para el dibujo del panel */

	@Override
	protected void agregarComponentesPanelInformacion()
	{
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[]{30, 1, 0};
		gridBagLayout.rowHeights = new int[]{1, 39, 1, 0};
		gridBagLayout.columnWeights = new double[]{1.0, 1.0, Double.MIN_VALUE};
		gridBagLayout.rowWeights = new double[]{1.0, 1.0, 1.0, Double.MIN_VALUE};
		
		this.getPanelDeInformacion().setLayout(gridBagLayout);
		
		this.agregarPanelNombre();
		this.agregarPanelPadre();
		this.agregarPanelTipoParticion();
		this.agregarPanelTipoSolapamiento();
		this.agregarPanelEntidadesEspecializadas();
	}

	private void agregarPanelEntidadesEspecializadas()
	{
		panelEntidadesEspecializadas= new PanelReferenciaEntidades("Entidades Especializadas");
		
		GridBagConstraints gbc_panelEntidadesEspecializadas = new GridBagConstraints();
		gbc_panelEntidadesEspecializadas.fill = GridBagConstraints.BOTH;
		gbc_panelEntidadesEspecializadas.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 0);
		gbc_panelEntidadesEspecializadas.gridwidth = 2;
		gbc_panelEntidadesEspecializadas.gridx = 0;
		gbc_panelEntidadesEspecializadas.gridy = 3;
		
		this.getPanelDeInformacion().add(panelEntidadesEspecializadas, gbc_panelEntidadesEspecializadas);
	}
	
	private void agregarPanelTipoSolapamiento() 
	{
		panelSolapamiento = new PanelBotonDeOpciones("Solapamiento");
		
		GridBagConstraints gbc_panelSolapamiento = new GridBagConstraints();
		gbc_panelSolapamiento.fill = GridBagConstraints.BOTH;
		gbc_panelSolapamiento.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 0);
		gbc_panelSolapamiento.gridx = 1;
		gbc_panelSolapamiento.gridy = 2;
		
		this.getPanelDeInformacion().add(panelSolapamiento, gbc_panelSolapamiento);
				
		JRadioButton optConSolapamiento = new JRadioButton("Si");
		optConSolapamiento.setToolTipText("Las instancias pueden pertenecer a mas de una entidad.");

		JRadioButton optSinSolapamiento = new JRadioButton("No", true);
		optSinSolapamiento.setToolTipText("Las instancias no pueden pertenecer a mas de una entidad.");
		
		panelSolapamiento.agregarBotonDeOpcion(optConSolapamiento);
		panelSolapamiento.agregarBotonDeOpcion(optSinSolapamiento);
	}

	private void agregarPanelTipoParticion() 
	{
		panelParticion = new PanelBotonDeOpciones("Particion");
		
		GridBagConstraints gbc_panelParticion = new GridBagConstraints();
		gbc_panelParticion.fill = GridBagConstraints.BOTH;
		gbc_panelParticion.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 5);
		gbc_panelParticion.gridx = 0;
		gbc_panelParticion.gridy = 2;
		
		this.getPanelDeInformacion().add(panelParticion, gbc_panelParticion);
					
		JRadioButton optParticionCompleta = new JRadioButton(ConstantesVista.PARTICION_COMPLETA, true);
		optParticionCompleta.setToolTipText("Las instancias deben pertenecer a alguna de las especializaciones.");
			
		JRadioButton optParticionParcial = new JRadioButton(ConstantesVista.PARTICION_PARCIAL);
		optParticionParcial.setToolTipText("Las instancias pueden pertenecer a la entidad padre.");
		
		panelParticion.agregarBotonDeOpcion(optParticionCompleta);
		panelParticion.agregarBotonDeOpcion(optParticionParcial);
	}

	private void agregarPanelPadre()
	{
		panelPadre = new PanelParLabelCombo("Entidad padre:");
		
		GridBagConstraints gbc_panelPadre = new GridBagConstraints();
		gbc_panelPadre.fill = GridBagConstraints.HORIZONTAL;
		gbc_panelPadre.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 0);
		gbc_panelPadre.gridwidth = 2;
		gbc_panelPadre.gridx = 0;
		gbc_panelPadre.gridy = 1;
		
		this.getPanelDeInformacion().add(panelPadre, gbc_panelPadre);
	}
	
	private void agregarPanelNombre()
	{
		panelNombre = new PanelParLabelText("Descripcion:");
		
		GridBagConstraints gbc_panelPadre = new GridBagConstraints();
		gbc_panelPadre.fill = GridBagConstraints.HORIZONTAL;
		gbc_panelPadre.insets = new Insets(0, 0, ConstantesVista.PANEL_INFORMACION_MARGEN_VERTICAL, 0);
		gbc_panelPadre.gridwidth = 2;
		gbc_panelPadre.gridx = 0;
		gbc_panelPadre.gridy = 0;
		
		this.getPanelDeInformacion().add(panelNombre, gbc_panelPadre);
	}

}